package com.zsp.comic.config.handler;


import com.alibaba.fastjson.JSONObject;
import com.zsp.comic.config.JWTConfig;
import com.zsp.comic.entity.SelfUserEntity;
import com.zsp.comic.entity.User;
import com.zsp.comic.service.UserService;
import com.zsp.comic.util.JWTTokenUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 这个过滤器很重要，没有这个过滤器的话前端传过来的token就无效
 *
 * @author gan
 * @create 2021-01-12 23:25
 */
@Component
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {

    @Resource
    private UserService userService;

    public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        // 获取请求头中JWT的Token
        String tokenHeader = request.getHeader("Authorization");

        Claims claims;

        if (null != tokenHeader) {
            try {
                // 解析JWT
                claims = Jwts.parser()
                        .setSigningKey("9277")
                        .parseClaimsJws(tokenHeader)
                        .getBody();
                // 获取用户名
                String username = claims.getSubject();
                String userId = claims.getId();


                if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(userId)) {
                    // 获取角色
                    List<GrantedAuthority> authorities = new ArrayList<>();
                    String authority = claims.get("authorities").toString();
                    if (!StringUtils.isEmpty(authority)) {
                        List<Map<String, String>> authorityMap = JSONObject.parseObject(authority, List.class);
                        for (Map<String, String> role : authorityMap) {
                            if (!StringUtils.isEmpty(role)) {
                                authorities.add(new SimpleGrantedAuthority(role.get("authority")));
                            }
                        }
                    }
                    //组装参数
                    SelfUserEntity selfUserEntity = new SelfUserEntity();
                    selfUserEntity.setUsername(claims.getSubject());
                    selfUserEntity.setUserId(Integer.parseInt(claims.getId()));
                    selfUserEntity.setAuthorities(authorities);

                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(selfUserEntity, userId, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (ExpiredJwtException e) {
                System.out.println("Token过期");
//                System.out.println(e);
//                claims = e.getClaims();
//                System.out.println(claims);
//                System.out.println(System.currentTimeMillis());
            } catch (Exception e) {
//                System.out.println("Token无效");
                System.out.println(e);
            }
        }


        chain.doFilter(request, response);
        return;
    }
}
